package org.annoflow.javassist;

import java.util.List;

import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.expr.Expr;
import javassist.expr.Handler;

import org.annoflow.javassist.AbstractCommand.CommandNotImplementedException;
import org.annoflow.javassist.AbstractCommand.SignatureType;
import org.apache.log4j.Logger;

/**
 * The Class InsertBefore. This class is used to represent an insert before
 * command. It is used to limit the types of expressions and methods that can be
 * translated.
 * 
 * translate InsertBefore <Class Name> <Method name> <Source body>
 * 
 */
public class InsertBefore implements CommandInterface
{
	private Logger logger = Logger.getLogger(InsertBefore.class);
	private List<String> configArgs;

	/**
	 * Instantiates a new insert before command.
	 * 
	 * @param args
	 *            the args
	 * 
	 * @throws MalformedCommandException
	 *             the malformed command exception
	 */
	public InsertBefore(List<String> args) throws MalformedCommandException
	{
		configArgs = args;
	}

	public void translate(Expr call, boolean isSuper)
			throws MalformedCommandException, CannotCompileException
	{
		if (call instanceof Handler)
		{
			translate((Handler) call);
			return;
		}
		throw new MalformedCommandException(
				"This command is not implemented for the parameters passed");

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cloudspace.vm.javassist.commands.CommandInterface#translate
	 * (javassist.CtMethod, java.lang.String)
	 */
	@Override
	public void translate(CtMethod member, String expressionName)
			throws MalformedCommandException, CannotCompileException,
			CommandNotImplementedException
	{
		throw new MalformedCommandException(
				"This command is not implemented for the parameters passed");
	}

	/**
	 * Translate.
	 * 
	 * @param call
	 *            the call
	 * 
	 * @throws MalformedCommandException
	 *             the malformed command exception
	 * @throws CannotCompileException
	 *             the cannot compile exception
	 */
	public void translate(Handler call) throws MalformedCommandException,
			CannotCompileException
	{
//		String signature;
//
//		signature = getSignature();
		call.insertBefore(getReplacement());
	}

	@Override
	public String getReplacement()
	{

		return configArgs.get(3).substring(1, configArgs.get(3).length() - 1);
	}

	@Override
	public String getSignature()
	{
		return configArgs.get(1);
	}

	@Override
	public SignatureType getSignatureType()
	{
		return SignatureType.STATICDEFINITION;
	}

	@Override
	public void translate(CtClass clazz) throws MalformedCommandException,
			CannotCompileException
	{
		CtClass superClazz;
		try
		{
			CtMethod[] meths = clazz.getDeclaredMethods();
			superClazz = clazz.getSuperclass();

			while (superClazz != null)
			{
				if (superClazz.getName().equals(getSignature()))
				{
					for (CtMethod meth : meths)
					{
						if (meth.getName().endsWith(configArgs.get(2)))
							meth.insertBefore(getReplacement());
					}
				}
				superClazz = superClazz.getSuperclass();
			}
		}
		catch (NotFoundException e)
		{
			logger.error("Method to translate not found",e);
			;
		}

	}

}
